package com.ruicar.afs.cloud.manage.finance.bankarrive.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.common.config.ContractFeginConfig;
import com.ruicar.afs.cloud.common.core.security.service.AfsUser;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.data.lock.anno.Lock;
import com.ruicar.afs.cloud.common.modules.contract.enums.AccountRegistStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ProcessStatus;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import com.ruicar.afs.cloud.common.modules.contract.enums.YesOrNoEnum;
import com.ruicar.afs.cloud.common.mq.finance.corporate.dto.GeneraSuccessDto;
import com.ruicar.afs.cloud.common.mq.rabbit.message.AfsTransEntity;
import com.ruicar.afs.cloud.common.mq.rabbit.message.MqTransCode;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.api.dto.BankArriveInfoDto;
import com.ruicar.afs.cloud.manage.api.feign.info.BasicMainInfoFeign;
import com.ruicar.afs.cloud.manage.finance.bankarrive.condition.BankArriveManagementCondition;
import com.ruicar.afs.cloud.manage.finance.bankarrive.entity.ManageAccountRegister;
import com.ruicar.afs.cloud.manage.finance.bankarrive.service.ManageAccountRegisterService;
import com.ruicar.afs.cloud.manage.finance.bankarrive.vo.FileStoreVo;
import com.ruicar.afs.cloud.manage.finance.corporate.entity.ManageCorporateTransfer;
import com.ruicar.afs.cloud.manage.finance.corporate.service.ManageCorporateTransferService;
import com.ruicar.afs.cloud.manage.mq.sender.ManageSender;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>Description: </p>
 *
 * @author ZC.GUO
 * @version 1.0
 * @date create on 2020-07-10 11:01
 */
@Slf4j
@RestController
@Api("银行到账管理")
@RequestMapping("/bankArriveManagement")
@AllArgsConstructor
public class BankArriveManagementController {

    private final ManageAccountRegisterService manageAccountRegisterService;
    private final ManageCorporateTransferService manageCorporateTransferService;

    private final ManageSender manageSender;
    private final BasicMainInfoFeign basicMainInfoFeign;
    private ContractFeginConfig contractFeginConfig;

    /**
     * 获取银行账号列表
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/queryBankArriveList")
    @ApiOperation(value = "多条件分页获取银行到账信息")
    public IResponse<IPage<ManageAccountRegister>> queryBankList(@ModelAttribute BankArriveManagementCondition bankArriveManagementCondition) {
        Page page = new Page(bankArriveManagementCondition.getPageNumber(), bankArriveManagementCondition.getPageSize());
        if (EmptyUtils.isNotEmpty(bankArriveManagementCondition.getStartDate())) {
            bankArriveManagementCondition.setStartDate(DateUtil.beginOfDay(bankArriveManagementCondition.getStartDate()));
        }
        if (EmptyUtils.isNotEmpty(bankArriveManagementCondition.getEndDate())) {
            bankArriveManagementCondition.setEndDate(DateUtil.endOfDay(bankArriveManagementCondition.getEndDate()));
        }
        IPage<ManageAccountRegister> manageAccountRegisterIPage = manageAccountRegisterService.page(page, Wrappers.<ManageAccountRegister>query().lambda()
                .like(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getEbankNo()), ManageAccountRegister::getEbankNo, bankArriveManagementCondition.getEbankNo())
                .like(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getCustName()), ManageAccountRegister::getPaymentCust, bankArriveManagementCondition.getCustName())
                .eq(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getArriveBank()), ManageAccountRegister::getBankAccount, bankArriveManagementCondition.getArriveBank())
                .eq(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getStatus()), ManageAccountRegister::getStatus, bankArriveManagementCondition.getStatus())
                .ge(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getStartDate()), ManageAccountRegister::getArrivalTime, bankArriveManagementCondition.getStartDate())
                .le(EmptyUtils.isNotEmpty(bankArriveManagementCondition.getEndDate()), ManageAccountRegister::getArrivalTime, bankArriveManagementCondition.getEndDate())
                .orderByAsc(ManageAccountRegister::getStatus)
        );
        return IResponse.success(manageAccountRegisterIPage);
    }

    /**
     * 根据对公勾稽案件编号查询银行到账记录列表
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/queryBankArriveListByCaseNo")
    @ApiOperation(value = "根据对公勾稽案件编号查询银行到账记录列表")
    public IResponse<List<ManageAccountRegister>> queryBankArriveListByCaseNo(@ModelAttribute BankArriveManagementCondition bankArriveManagementCondition) {
        List<ManageAccountRegister> manageAccountRegisterList = manageAccountRegisterService.list(Wrappers.<ManageAccountRegister>query().lambda()
                .eq(ManageAccountRegister::getCaseId, bankArriveManagementCondition.getCaseId())
                .orderByAsc(ManageAccountRegister::getArrivalTime)
        );
        return IResponse.success(manageAccountRegisterList);
    }


    /**
     * 删除指定银行到账信息
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/deleteAccountRegister")
    @ApiOperation(value = "删除银行到账信息")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<String> deleteAccountRegister(@ModelAttribute BankArriveManagementCondition bankArriveManagementCondition) {
        ManageAccountRegister manageAccountRegister = manageAccountRegisterService.getById(bankArriveManagementCondition.getId());
        if (manageAccountRegister != null && AccountRegistStatusEnum.NOT_GENERA.equals(manageAccountRegister.getStatus())) {
            manageAccountRegisterService.removeById(manageAccountRegister.getId());
            return IResponse.success("删除成功");
        } else {
            return IResponse.success("删除失败");
        }
    }

    /**
     * 指定银行到账信息生成凭证
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/generaAccountRegister")
    @ApiOperation(value = "指定银行到账信息生成凭证")
    public IResponse<String> generaAccountRegister(@ModelAttribute BankArriveManagementCondition bankArriveManagementCondition) {
        List<Long> idList = Arrays.stream(bankArriveManagementCondition.getIds().split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        List<ManageAccountRegister> manageAccountRegisterList = manageAccountRegisterService.list(Wrappers.<ManageAccountRegister>query().lambda()
                .in(ManageAccountRegister::getId, idList)
                .eq(ManageAccountRegister::getStatus, AccountRegistStatusEnum.NOT_GENERA)
        );
        if (EmptyUtils.isNotEmpty(manageAccountRegisterList)) {
            for (ManageAccountRegister manageAccountRegister : manageAccountRegisterList) {
                manageAccountRegisterService.handleAccountRegister(manageAccountRegister);
            }
        } else {
            return IResponse.fail("生成凭证失败");
        }
        return IResponse.success("生成凭证成功");

    }

    /**
     * 添加银行账户
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/addSubmit")
    @ApiOperation(value = "添加银行账户")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<String> addSubmit(@RequestBody ManageAccountRegister manageAccountRegister) {

        ManageAccountRegister accountRegister = manageAccountRegisterService.getOne(Wrappers.<ManageAccountRegister>query().lambda()
                .eq(ManageAccountRegister::getEbankNo, manageAccountRegister.getEbankNo())
                .ne(ManageAccountRegister::getStatus, AccountRegistStatusEnum.WRITE_BACK)
                .ne(ManageAccountRegister::getStatus, AccountRegistStatusEnum.REFUND)
        );
        if (accountRegister != null) {
            return IResponse.fail("网银编号重复，添加失败");
        } else {
            manageAccountRegister.setStatus(AccountRegistStatusEnum.ALREADY_GENERA);
            manageAccountRegister.setIsOperating(YesOrNoEnum.no);
            manageAccountRegisterService.save(manageAccountRegister);
            /**  发送记录到账务服务 by ZC.GUO  **/
            GeneraSuccessDto generaSuccessDto = new GeneraSuccessDto();
            AfsUser user = SecurityUtils.getUser();
            generaSuccessDto.setOperator(user == null ? null : user.getUsername());
            generaSuccessDto.setFundId(manageAccountRegister.getId());
            generaSuccessDto.setAmount(manageAccountRegister.getReceivedAmt());
            generaSuccessDto.setFeeSourceTable(ManageAccountRegister.class.getAnnotation(TableName.class).value());
            generaSuccessDto.setSourceAccount(manageAccountRegister.getCustAccount());
            generaSuccessDto.setCreditAccount(manageAccountRegister.getBankAccount());
            generaSuccessDto.setContractNo(manageAccountRegister.getContractNo());
            generaSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.unknownCollection);
            AfsTransEntity<GeneraSuccessDto> entity = new AfsTransEntity<>();
            entity.setData(generaSuccessDto);
            entity.setTransCode(MqTransCode.AFS_CONTRACT_MANAGE_FINANCE_CONTRACT_GENERA_SUCCESS);
            manageSender.sendGeneraSuccessDataToFinance(entity);
            return IResponse.success("添加成功");
        }
    }

    /**
     * 查询银行到账信息
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/getBankArriveInfo")
    @ApiOperation(value = "查询银行到账信息")
    public IResponse<BankArriveInfoDto> getBankArriveInfo(@RequestParam("id") Long id) {
        BankArriveInfoDto bankArriveInfoDto = new BankArriveInfoDto();
        ManageAccountRegister manageAccountRegister = manageAccountRegisterService.getById(id);
        if (EmptyUtils.isNotEmpty(manageAccountRegister)) {
            bankArriveInfoDto.setArrivalTime(manageAccountRegister.getArrivalTime());
            bankArriveInfoDto.setPaymentCust(manageAccountRegister.getPaymentCust());
            bankArriveInfoDto.setReceivingBank(manageAccountRegister.getReceivingBank());
            bankArriveInfoDto.setSummary(manageAccountRegister.getSummary());
            ManageCorporateTransfer corporateTransfer = manageCorporateTransferService.getById(manageAccountRegister.getCaseId());
            if (EmptyUtils.isNotEmpty(corporateTransfer)) {
                bankArriveInfoDto.setDealRemarks(corporateTransfer.getReason());
            }
            return IResponse.success(bankArriveInfoDto);
        } else {
            return IResponse.fail("不存在的银行到账id");
        }
    }

    /**
     * 修改银行账户
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/editSubmit")
    @ApiOperation(value = "修改银行账户")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<Object> editSubmit(@RequestBody ManageAccountRegister manageAccountRegister) {
        ManageAccountRegister accountRegister = manageAccountRegisterService.getOne(Wrappers.<ManageAccountRegister>query().lambda()
                .eq(ManageAccountRegister::getEbankNo, manageAccountRegister.getEbankNo())
                .ne(ManageAccountRegister::getStatus, AccountRegistStatusEnum.WRITE_BACK)
                .ne(ManageAccountRegister::getStatus, AccountRegistStatusEnum.REFUND)
                .ne(ManageAccountRegister::getId, manageAccountRegister.getId())
        );
        if (accountRegister != null) {
            return IResponse.fail("网银编号重复，编辑失败");
        } else {
            manageAccountRegisterService.updateById(manageAccountRegister);
            return IResponse.success("编辑成功");
        }
    }


    /**
     * Upload response
     * <p>Description: </p>
     *
     * @param file file
     * @return the response
     */
    @PostMapping("/importRegister")
    public IResponse<FileStoreVo> importRegister(@RequestParam("file") MultipartFile file,@RequestParam("batchDate") Date batchDate) throws IOException {
        if (file.isEmpty()) {
            return IResponse.fail("请上传正确文件").setCode(ProcessStatus.ILLEGAL.getCode()).setMsg("请上传正确文件").setData(JSONUtil.parseArray("[{\"msg\":\"请上传正确文件\"}]"));
        }
        /**  文件格式 by ZC.GUO  **/
        String fileType = FileUtil.extName(file.getOriginalFilename());
        String rightFileType = "xlsx";
        if (!rightFileType.equals(fileType)) {
            return IResponse.fail("请上传与模板格式一致的excel文件").setCode(ProcessStatus.ILLEGAL.getCode()).setMsg("请上传与模板格式一致的excel文件").setData(JSONUtil.parseArray("[{\"msg\":\"请上传与模板格式一致的excel文件\"}]"));
        }
        /**  文件解析 by ZC.GUO  **/
        try {
            List<ManageAccountRegister> accountRegisterList = manageAccountRegisterService.handleExcelImport(file,batchDate);
            if (EmptyUtils.isNotEmpty(accountRegisterList)) {
                try {
                    manageAccountRegisterService.handleAccountRegisterStatus(accountRegisterList);
                } catch (Exception e) {
                    log.info(e.getMessage());
                }
            }

        } catch (Exception e) {
            log.info(e.getMessage());
            return IResponse.fail(e.getMessage()).setCode(ProcessStatus.ILLEGAL.getCode()).setMsg(e.getMessage()).setData(JSONUtil.parseArray("[{\"msg\":\"" + e.getMessage() + "\"}]"));
        }
        return IResponse.success(FileStoreVo.builder().build());
    }

    /**
     * 红冲凭证
     *
     * @param
     * @return
     */
    @PostMapping(value = "/writeBack")
    @ApiOperation(value = "红冲凭证")
    @Lock(keyConstant = ":accountRegister", keys = "#manageAccountRegister.id")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<String> writeBack(@ModelAttribute BankArriveManagementCondition bankArriveManagementCondition) {
        List<Long> idList = Arrays.stream(bankArriveManagementCondition.getIds().split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        List<ManageAccountRegister> manageAccountRegisterList = manageAccountRegisterService.list(Wrappers.<ManageAccountRegister>query().lambda()
                .in(ManageAccountRegister::getId, idList)
                .eq(ManageAccountRegister::getStatus, AccountRegistStatusEnum.ALREADY_GENERA)
        );
        if (EmptyUtils.isNotEmpty(manageAccountRegisterList)) {
            for (ManageAccountRegister manageAccountRegister : manageAccountRegisterList) {
                manageAccountRegisterService.update(Wrappers.<ManageAccountRegister>lambdaUpdate()
                        .eq(ManageAccountRegister::getId, manageAccountRegister.getId())
                        .eq(ManageAccountRegister::getStatus, AccountRegistStatusEnum.ALREADY_GENERA)
                        .set(ManageAccountRegister::getStatus, AccountRegistStatusEnum.WRITE_BACK)
                );
                /**  发送记录到账务服务 by ZC.GUO  **/
                GeneraSuccessDto generaSuccessDto = new GeneraSuccessDto();
                AfsUser user = SecurityUtils.getUser();
                generaSuccessDto.setOperator(user == null ? null : user.getUsername());
                generaSuccessDto.setFundId(manageAccountRegister.getId());
                generaSuccessDto.setAmount(manageAccountRegister.getReceivedAmt());
                generaSuccessDto.setFeeSourceTable(ManageAccountRegister.class.getAnnotation(TableName.class).value());
                generaSuccessDto.setSourceAccount(manageAccountRegister.getCustAccount());
                generaSuccessDto.setCreditAccount(manageAccountRegister.getBankAccount());
                generaSuccessDto.setContractNo(manageAccountRegister.getContractNo());
                generaSuccessDto.setBuriedPointNo(VoucherBuriedPointNo.unknownCollectionRetrun);
                AfsTransEntity<GeneraSuccessDto> entity = new AfsTransEntity<>();
                entity.setData(generaSuccessDto);
                entity.setTransCode(MqTransCode.AFS_CONTRACT_MANAGE_FINANCE_CONTRACT_GENERA_SUCCESS);
                manageSender.sendGeneraSuccessDataToFinance(entity);
            }
        } else {
            return IResponse.fail("生成凭证失败");
        }
        return IResponse.success("生成凭证成功");

    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }
}
